#include "XEventListener.h"
#include "XGraphicsSubsystem.h"

#include "XGLWindow.h"
#include "XWindowImpl.h"

#include <X11/Xlib.h>
#include <X11/keysym.h>

#include "gui/EventManager.h"
#include "gui/Events.h"
#include "core/VirtualKeyCodes.h"

using namespace neiderra::core;
using namespace neiderra::gui;
using namespace neiderra::gui::events;

XEventListener::XEventListener(Core* core, Display* display) : EventListener(core)
{
	_display = display;
}

int XEventListener::listen()
{
 	iGUIEvent* guiEvent=0;
	GUIMouseEvent* mouseEvent=0;
	GUIKeyEvent* keyEvent=0;
	
	XEvent e;
	XGLWindow* window=0;
	XGraphicsSubsystem* xgrs;
	KeySym key_symbol;
	
	if(!XPending(_display)) return 0;
		
	XNextEvent(_display, &e);
	
	xgrs = dynamic_cast<XGraphicsSubsystem*>(core->getGraphicsSubsystem());
	if(xgrs)
	{
		/*window = (XGLWindow*) xgrs->GetWindowPointer(e.window);
		if(window)
			return ((XWindowImpl*)(window->getWindowImpl()))->ResponseEvent( e );
		else return -1;*/
		
		switch(e.type)
		{
			case Expose: 
				window = (XGLWindow*) xgrs->GetWindowPointer(e.xexpose.window);
				if(window)
					window->getWindowImpl()->update();
			break;
			case MapNotify:
				window = (XGLWindow*) xgrs->GetWindowPointer(e.xmaprequest.window);
				if(window)
					window->getWindowImpl()->show();
				break;
			case ButtonPress:
				window = (XGLWindow*) xgrs->GetWindowPointer( e.xbutton.window );
//				cout << "\tClick( " << e.xbutton.x << ", " << e.xbutton.y << " )" << endl;
				mouseEvent = new GUIMouseEvent();
				mouseEvent->type = GUIMouseEvent::mouse_down;
				mouseEvent->pwin = window;
				mouseEvent->mx = e.xbutton.x;
				mouseEvent->my = e.xbutton.y;
				guiEvent = mouseEvent;
				break;
			case KeyPress:
				window = (XGLWindow*) xgrs->GetWindowPointer( e.xbutton.window );
				keyEvent = new GUIKeyEvent();
				keyEvent->type = GUIKeyEvent::key_down;
				key_symbol = XKeycodeToKeysym(_display, e.xkey.keycode, 0);
				keyEvent->keycode = KeySymToKeyCode(key_symbol);
				guiEvent = keyEvent;
				break;
			case KeyRelease:
// 				sysEvent = new sysShutDownEvent();
				break;
			default:
				return 0;
		}
		
		core->getGraphicsSubsystem()->getEventManager()->pushEvent(guiEvent);
		
/*		if ( sysEvent )
			core->getEventManager()->pushEvent( sysEvent );*/
	}		
	
	return -1;
}

XEventListener::~XEventListener()
{
}

unsigned neiderra::gui::KeySymToKeyCode(KeySym keysym)
{
	// temp solution !
	KeyboardCodes keycode = vk_default;
	switch(keysym)
	{
		case XK_Escape:
			keycode = vk_esc;
			break;
	}
	return keycode;
}
